home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / Snippets / Processes / KillEveryOneButMe / KillEveryOneButMe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-18  |  20.5 KB  |  568 lines  |  [TEXT/MPS ]

  1. /* KillEveryBodyButMe.c */
  2. /* Some folks want to kill all the other applications running on a machine */
  3. /* for demos, school situations, kiosks, etc. */
  4. /* with System 7, it's easy, just use the Process Manager and AppleEvents. */
  5. /* This thing shows you how. */
  6. /* PLEASE don't abuse this.  System 7 gives the user full-time multiFinder, and they */
  7. /* like it, our System Software team worked very hard to make this */
  8. /* happen.  ONLY do this in very special circumstances, or you're taking */
  9. /* power away from the user and weaking the strength of the Mac. */
  10. /* Written  by C.K. Haun <TR> */
  11. /* Apple Developer Tech Support */
  12.  
  13. /* BUG FIX, if only this app and the Finder were/was running, it didn't do anything */
  14. /* Ooops */
  15.  
  16. /* Of course, Copyright 1991-1992, Apple Computer Inc. */
  17. #include <Types.h>
  18. #include <memory.h>
  19. #include <Packages.h>
  20. #include <Errors.h>
  21. #include <quickdraw.h>
  22. #include <fonts.h>
  23. #include <dialogs.h>
  24. #include <windows.h>
  25. #include <menus.h>
  26. #include <events.h>
  27. #include <OSEvents.h>
  28. #include <Desk.h>
  29. #include <diskinit.h>
  30. #include <OSUtils.h>
  31. #include <resources.h>
  32. #include <toolutils.h>
  33. #include <AppleEvents.h>
  34. #include <EPPC.h>
  35. #include <GestaltEqu.h>
  36. #include <PPCToolbox.h> 
  37. #include <Processes.h>
  38. #include <Balloons.h>
  39. /* prototypes */
  40. void InitalizeApp(void);
  41. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  42. void DrawMain(WindowPtr drawIt);
  43. Boolean DoSelected(long val);
  44.  
  45. void InitAEStuff(void);
  46. void DoHighLevel(EventRecord *AERecord);
  47. void DoDaCall(MenuHandle themenu, long theit);
  48. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  49. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  50. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  51. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  52. void SampleHelpDialog(void);
  53. void KillEveryBody(void);
  54. /* one external */
  55. extern void _DataInit();                                    /* this is the C initialization code */
  56.  
  57. #define kMBarID 128
  58. #define kAppleMenu 128
  59. #define kFileMenu 129
  60. #define kEditMenu 130
  61. #define kToolsMenu 131
  62. #define kResumeMask             1       /* bit of message field for resume vs. suspend */
  63. #define kSampHelp 129
  64. #define kAboutBox 128
  65. #define kHelpString 128
  66. #define kNewItem 1
  67. #define kOpenItem 2
  68. #define kCloseItem 3
  69. #define kSaveItem 4
  70. #define kSaveAsItem 5
  71. #define kFileBlank1 6
  72. #define kPageSetupItem 7
  73. #define kPrintItem 8
  74. #define kFileBlank2 9
  75. #define kQuitItem 10
  76. #define kBadSystem 130
  77. #define kTitle 129
  78. struct AEinstalls {
  79.     AEEventClass theClass;
  80.     AEEventID theEvent;
  81.     EventHandlerProcPtr theProc;
  82. };
  83. typedef struct AEinstalls AEinstalls;
  84.  
  85. Handle gMymenu;                                             /* my menu bar handle */
  86. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle;
  87. Boolean gQuit, gInBackground;
  88. EventRecord gERecord;
  89. AEDesc gTheAddress;
  90. WindowPtr myWindow;
  91. ProcessSerialNumber gOurSN;
  92. short gHelpItem;
  93.  
  94. #pragma segment Main
  95. main()
  96. {
  97.     WindowPtr twindow;
  98.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  99.     InitalizeApp();
  100.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  101.     do {
  102.         WaitNextEvent(everyEvent, &gERecord, 30, nil);
  103.         switch (gERecord.what) {
  104.             
  105.             case nullEvent:
  106.                 /* no nul processing in this sample */
  107.                 break;
  108.             case updateEvt:
  109.                 DrawMain((WindowPtr)gERecord.message);      /* draw whatever window needs an update */
  110.                 break;
  111.             case mouseDown:
  112.                 /* first see where the hit was */
  113.                 switch (FindWindow(gERecord.where, &twindow)) {
  114.                     
  115.                     case inDesk:                            /* if they hit in desk, then the process manager */
  116.                         break;                              /* will switch us out, we don't need to do anything */
  117.                     case inMenuBar:
  118.                         DoSelected(MenuSelect(gERecord.where));
  119.                         break;
  120.                         
  121.                     case inSysWindow:
  122.                         /* pass to the system */
  123.                         SystemClick(&gERecord, twindow);
  124.                         break;
  125.                     case inContent:
  126.                         /* Handle content and control clicks here */
  127.                         break;
  128.                     case inDrag:
  129.                         if (twindow == FrontWindow())
  130.                             DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  131.                         break;
  132.                     case inGrow:
  133.                         /* Call GrowWindow here if you have a grow box */
  134.                         break;
  135.                     case inGoAway:
  136.                         /* Click in Close box */
  137.                         break;
  138.                         
  139.                 }
  140.             case mouseUp:
  141.                 /* don't care */
  142.                 break;
  143.                 /* same action for key or auto key */
  144.             case keyDown:
  145.             case autoKey:
  146.                 if (gERecord.modifiers & cmdKey)
  147.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  148.                 break;
  149.             case keyUp:
  150.                 /* don't care */
  151.                 break;
  152.             case diskEvt:
  153.                 /* I don't do anything special for disk events, this just passes them */
  154.                 /* to a function that checks for an error on the mount */
  155.                 DoDiskEvents(gERecord.message);
  156.                 break;
  157.             case activateEvt:
  158.                 if (gERecord.modifiers & activeFlag){
  159.                     SetPort(myWindow);
  160.                     DrawMain((WindowPtr)gERecord.message);
  161.                     }
  162.                 break;
  163.             case networkEvt:
  164.                 /* don't care */
  165.                 break;
  166.             case driverEvt:
  167.                 /* don't care */
  168.                 break;
  169.             case app4Evt:
  170.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  171.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  172.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  173.                         break;
  174.                 }
  175.                 break;
  176.             default:
  177.                 break;
  178.                 /* This dispatches high level events (AppleEvents, for example) */
  179.                 /* to our dispatch routine.  This is NEW in the event loop for */
  180.                 /* System 7 */
  181.             case kHighLevelEvent:
  182.                 DoHighLevel(&gERecord);
  183.                 break;
  184.                 
  185.         }
  186.     }
  187.             while (gQuit != true);
  188.     
  189. }
  190.  
  191. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  192. /* like to perform some action or just know when a DA is opened in your */
  193. /* layer.  Can be handy to track memory problems when a DA is opened */
  194. /* with an Option-open */
  195. void DoDaCall(MenuHandle themenu, long theit)
  196. {
  197.     long qq;
  198.     char DAname[255];
  199.     GetItem(themenu, theit, &DAname);
  200.     qq = OpenDeskAcc(DAname);
  201. }
  202.  
  203. /* end DoDaCall */
  204.  
  205. /* DoDiskEvents just checks the error code from the disk mount, */
  206. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  207. /* You can do much more here if you care about what disks are */
  208. /* in the drive */
  209. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  210. {
  211.     short hival, loval, tommy;
  212.     Point fredpoint =  {
  213.         40, 40
  214.     };
  215.     hival = HiWord(dinfo);
  216.     loval = LoWord(dinfo);
  217.     if (hival != noErr)                                     /* something happened */ {
  218.         tommy = DIBadMount(fredpoint, dinfo);
  219.     }
  220. }
  221.  
  222. /* draws my window.  Pretty simple */
  223. void DrawMain(WindowPtr drawIt)
  224. {
  225.     short vPos, hPos;
  226.     short incre = 20;
  227.     short oldFace;
  228.     ProcessInfoRec infoRec;
  229.     StringHandle theString;
  230.     OSErr myErr;
  231.     Str31 processName;
  232.     FSSpec procSpec;
  233.     ProcessSerialNumber processSN;
  234.     processSN.lowLongOfPSN = kNoProcess;
  235.     processSN.highLongOfPSN = kNoProcess;
  236.     vPos = 15;
  237.     hPos = 20;
  238.     BeginUpdate(drawIt);
  239.     SetPort(drawIt);
  240.     EraseRect(&drawIt->portRect);
  241.     MoveTo(hPos, vPos);
  242.     theString = GetString(kTitle);
  243.     HLock((Handle)theString);
  244.     oldFace = drawIt->txFace;
  245.     TextFace(bold);
  246.     DrawString((ConstStr255Param)*theString);
  247.     TextFace(oldFace);
  248.     ReleaseResource((Handle)theString);
  249.     vPos += incre;
  250.     do {
  251.         myErr = GetNextProcess(&processSN);
  252.         
  253.         infoRec.processInfoLength = sizeof(ProcessInfoRec);
  254.         infoRec.processName = &processName;
  255.         infoRec.processAppSpec = &procSpec;
  256.         myErr = GetProcessInformation(&processSN, &infoRec);
  257.         if (!myErr) {
  258.             MoveTo(hPos, vPos);
  259.             DrawString(infoRec.processName);
  260.             vPos += incre;
  261.         }
  262.     }
  263.             while (myErr == noErr);
  264.     
  265.     EndUpdate(drawIt);
  266. }
  267.  
  268. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  269. /* mught be handy someday */
  270. Boolean DoSelected(long val)
  271. {
  272.     short loval, hival;
  273.     Boolean returnVal = false;
  274.     loval = LoWord(val);
  275.     hival = HiWord(val);
  276.     
  277.     switch (hival) {                                        /* switch off the menu number selected */
  278.         case kAppleMenu:                                    /* Apple menu */
  279.             if (loval != 1) {                               /* if this was not About, it's a DA */
  280.                 DoDaCall(gAppleMenuHandle, loval);
  281.             } else {
  282.                 Alert(kAboutBox, nil);                      /* do about box */
  283.             }
  284.             returnVal = true;
  285.             break;
  286.         case kFileMenu:                                     /* File menu */
  287.             switch (loval) {
  288.                 case kQuitItem:
  289.                     gQuit = true;                           /* only  item */
  290.                     returnVal = true;
  291.                     break;
  292.                 default:
  293.                     break;
  294.             }
  295.             break;
  296.         case kEditMenu:
  297.             /* edit menu junk */
  298.             /* don't care */
  299.             break;
  300.         case kToolsMenu:
  301.             /* add all your test stuff here */
  302.             /* only one item, kill stuff */
  303.             KillEveryBody();
  304.             InvalRect(&myWindow->portRect);
  305.             break;
  306.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  307.             /* I only care about this item.  If anything else is returned here, I don't know what */
  308.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  309.             /* Apple reserves the right to add and change things in the Help menu */
  310.             if (loval == gHelpItem)
  311.                 SampleHelpDialog();
  312.             break;
  313.             
  314.     }
  315.     HiliteMenu(0);
  316.     return(returnVal);
  317. }
  318.  
  319. /* InitAEStuff installs my appleevent handlers */
  320. void InitAEStuff(void)
  321. {
  322.     static AEinstalls HandlersToInstall[] =  {
  323.         {
  324.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  325.         },  {
  326.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  327.         },  {
  328.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  329.         },  {
  330.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  331.         }, 
  332.         /* The above are the four required AppleEvents. */
  333.         
  334.     };
  335.     
  336.     OSErr aevtErr = noErr;
  337.     long aLong = 0;
  338.     Boolean gHasAppleEvents = false;
  339.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  340.     *   then we exit */
  341.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  342.     /* The following series of calls installs all our AppleEvent Handlers.
  343.     *   These handlers are added to the application event handler list that 
  344.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  345.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  346.     *   list of handlers and dispatch to it if there is one.
  347.     */
  348.     if (gHasAppleEvents) {
  349.         register qq;
  350.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  351.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  352.                                             HandlersToInstall[qq].theProc, 0, false);
  353.             if (aevtErr) {
  354.                 ExitToShell();                              /* just fail, baby */
  355.             }
  356.         }
  357.     } else {
  358.         ExitToShell();
  359.     }
  360. }
  361.  
  362. /* end InitAEStuff */
  363. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  364. /* easy for me to say, huh? */
  365. void DoHighLevel(EventRecord *AERecord)
  366. {
  367.     
  368.     AEProcessAppleEvent(AERecord);
  369.     
  370. }
  371.  
  372. /* end DoHighLevel */
  373.  
  374. /* This is the standard Open Application event.  */
  375. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  376. {
  377. #pragma unused (messagein,reply,refIn)
  378.     /* we of course don't do anything here in this simple app */
  379.     /* except open our window */
  380.     myWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  381.     SetPort(myWindow);
  382.     return(noErr);
  383. }
  384.  
  385. /* end AEOpenHandler */
  386.  
  387. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  388. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  389. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  390. /* handler will get called. Which means you don't do any initialization of globals here, or */
  391. /* anything else except open then doc.  */
  392. /* SO-- Do NOT assume that you are at app start time in this */
  393. /* routine, or bad things will surely happen to you. */
  394.  
  395. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  396. {
  397. #pragma unused (messagein,refIn,reply)
  398.     /* we of course don't do anything here */
  399.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  400. }
  401.  
  402. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  403. {                                                           /* no printing handler in yet, so we'll ignore this */
  404.     /* the operation is functionally identical to the ODOC event, with the additon */
  405.     /* of calling your print routine.  */
  406. #pragma unused (messagein,refIn,reply)
  407.     /* we of course don't do anything here */
  408.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  409. }
  410.  
  411. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  412. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  413. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  414. {
  415. #pragma unused (messagein,refIn,reply)
  416.     
  417.     /* prepQuit sets the Stop flag for us.  It does _NOT_ quit, you */
  418.     /* should NEVER quit from an AppleEvent handler.  Calling */
  419.     /* ExitToShell here would blow things up */
  420.     gQuit = true;
  421.     return(noErr);
  422. }
  423.  
  424.  
  425. /* This is my sample help dialog.  Does not do anything, expand as you need */
  426. void SampleHelpDialog(void)
  427. {
  428.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  429.     short itemhit = 0;
  430.     while (itemhit != 1) {
  431.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  432.     }
  433.     DisposDialog(tdial);
  434. }
  435.  
  436.  
  437. /* This is the killer code.  It finds and kills every other  */
  438. /* application on your machine. */
  439. void KillEveryBody(void)
  440. {
  441.     ProcessSerialNumber myProc, processSN;
  442.     ProcessSerialNumber finderPSN;
  443.     ProcessInfoRec infoRec;
  444.     Str31 processName;
  445.     FSSpec procSpec;
  446.     
  447.     OSErr myErr = noErr;
  448.     OSErr otherError;
  449.     AppleEvent theEvent;
  450.     AEDesc theAddress;
  451.     Boolean ourFlag, notFinder;
  452.     Boolean finderFound = false;
  453.     GetCurrentProcess(&myProc);
  454.     /* Preset the PSN to no PSN, see IM VI, the Process Manager */
  455.     processSN.lowLongOfPSN = kNoProcess;
  456.     processSN.highLongOfPSN = kNoProcess;
  457.     finderPSN.lowLongOfPSN = nil;
  458.     finderPSN.highLongOfPSN = nil;
  459.     
  460.     do {
  461.         myErr = GetNextProcess(&processSN);
  462.         /* See if it's us first */
  463.         notFinder = true;
  464.         SameProcess(&myProc, &processSN, &ourFlag);
  465.  
  466.             infoRec.processInfoLength = sizeof(ProcessInfoRec);
  467.             infoRec.processName = &processName;
  468.             infoRec.processAppSpec = &procSpec;
  469.             GetProcessInformation(&processSN, &infoRec);
  470.         if (!ourFlag && !finderFound) {
  471.             /* see if it's the Finder, we have to kill the finder LAST */
  472.             /* or else non-sys 7 apps won't get killed */
  473.             /* since the Finder must be there to convert the AppleEvent to Puppet Strings */
  474.             /* if the app is not APpleEvent aware */
  475.             /* Also, FileShare HAS to be killed before the Finder */
  476.             /* or your life will be unpleasant */
  477.  
  478.             if (infoRec.processSignature == 'MACS' && infoRec.processType == 'FNDR') {
  479.                 /* save this number for later  */
  480.                 finderPSN = processSN;
  481.                 notFinder = false;
  482.                 finderFound = true;
  483.             
  484.             } else {
  485.                 notFinder = true;
  486.             }
  487.         }
  488.         if (!myErr && !ourFlag && notFinder) {
  489.             otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&processSN, sizeof(processSN), &theAddress);
  490.             if (!otherError)
  491.                 otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,
  492.                                                 kAnyTransactionID, &theEvent);
  493.             if (!otherError)
  494.                 AEDisposeDesc(&theAddress);
  495.             /* Again, the Finder will convert the AppleEvent to puppetstrings if */
  496.             /* the application is a System 6 or non-AE aware app.  This ONLY  */
  497.             /* happens for the 4 required (oapp,odoc,pdoc, and quit) AppleEvents  */
  498.             /* and ONLY if you use the PSN for the address */
  499.             if (!otherError)
  500.                 AESend(&theEvent, nil, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
  501.                        nil, nil);
  502.             AEDisposeDesc(&theEvent);
  503.         }
  504.     } while (!myErr);
  505.     
  506.     /* Now, if the finder was running, it's safe to kill it */
  507.     if (finderPSN.lowLongOfPSN || finderPSN.highLongOfPSN) {
  508.         otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(processSN), &theAddress);
  509.         if (!otherError)
  510.             otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,
  511.                                             kAnyTransactionID, &theEvent);
  512.         if (!otherError)
  513.             AEDisposeDesc(&theAddress);
  514.         if (!otherError)
  515.             AESend(&theEvent, nil, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, nil,
  516.                    nil);
  517.         AEDisposeDesc(&theEvent);
  518.     }
  519. }
  520.  
  521.  
  522. #pragma segment Initialize
  523. void InitalizeApp(void)
  524. {
  525.     MenuHandle helpHandle;
  526.     StringHandle helpString;
  527.     short count;
  528.     long vers;
  529.     MaxApplZone();
  530.     InitGraf((Ptr)&qd.thePort);
  531.     InitFonts();
  532.     InitWindows();
  533.     InitMenus();
  534.     TEInit();
  535.     InitDialogs(nil);
  536.     InitCursor();
  537.     /* Check system version */
  538.     Gestalt(gestaltSystemVersion, &vers);
  539.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  540.     if (vers < 7) {
  541.         StopAlert(kBadSystem, nil);
  542.         ExitToShell();
  543.     }
  544.     InitAEStuff();
  545.     /* set up my menu junk */
  546.     gMymenu = GetNewMBar(kMBarID);
  547.     SetMenuBar(gMymenu);
  548.     gAppleMenuHandle = GetMHandle(kAppleMenu);
  549.     gFileMenuHandle = GetMHandle(kFileMenu);
  550.     gEditMenuHandle = GetMHandle(kEditMenu);
  551.     gToolMenuHandle = GetMHandle(kToolsMenu);
  552.     AddResMenu(gAppleMenuHandle, 'DRVR');
  553.     /* now install my Help menu item in the Help Manager's menu */
  554.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  555.     count = CountMItems(helpHandle);                        /* How many items are there? */
  556.     helpString = GetString(kHelpString);                    /* get my help string */
  557.     DetachResource(helpString);                             /* detach it */
  558.     HNoPurge(helpString);
  559.     MoveHHi((Handle)helpString);
  560.     HLock((Handle)helpString);
  561.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  562.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  563.     
  564.     DrawMenuBar();
  565.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  566.     
  567. }
  568.